﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Caifu.Clients;

namespace Caifu
{
	/// <summary>
	/// 交易日期使用类。
	/// </summary>
	public static class TradeDateUtil
	{
		/// <summary>
		/// 获取所有非交易日集合。
		/// 首先从当前进程缓存查询，如果不存在则从数据源查询，并缓存至当前进程，有效时间5分钟。
		/// </summary>
		/// <returns></returns>
		public static IList<NontradeDate> GetAllNontradeDates()
		{
			string key = "Caifu.NontradeDate.List";
			return CaifuUtil.GetValueFromCache(key, NontradeDateClient.GetAllNontradeDate, new TimeSpan(0, 5, 0));
		}

		/// <summary>
		/// 获取所有非交易日字典。
		/// 首先从当前进程缓存查询，如果不存在则从数据源查询，并缓存至当前进程，有效时间5分钟。
		/// </summary>
		/// <returns></returns>
		public static Dictionary<DateTime, NontradeDate> GetAllNontradeDateDict()
		{
			string key = "Caifu.NontradeDate.Dict";
			return CaifuUtil.GetValueFromCache(key,
				() => { return GetAllNontradeDates().ToDictionary(p => p.Date, p => p); }
				, new TimeSpan(0, 5, 0)
			);

		}

		/// <summary>
		/// 检查指定日期是否为交易日。
		/// </summary>
		/// <param name="date">指定日期</param>
		/// <returns></returns>
		public static bool CheckIsTradeDate(DateTime date)
		{
			if (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday)
			{
				return false;
			}
			var dict = GetAllNontradeDateDict();

			return !dict.ContainsKey(date);

		}

		/// <summary>
		/// 获取当前的每日净值日期。
		/// 即：每日净值中应该显示哪天净值。
		/// 简单判断节假日，如需精确判断需要使用其它类库。
		/// </summary>
		/// <returns></returns>
		public static DateTime GetNetDailyDate()
		{
			DateTime date;
			var now = DateTime.Now;
			var hour = now.Hour;

			if (now.Date.DayOfWeek == DayOfWeek.Saturday)
			{
				date = now.Date.AddDays(-1);
			}
			else if (now.Date.DayOfWeek == DayOfWeek.Sunday)
			{
				date = now.Date.AddDays(-2);
			}
			else if (hour > 18)
			{
				date = now.Date;
			}
			else
			{
				date = now.Date.AddDays(-1);
			}
			return date;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public static DateTime GetPreviousTradeDate(DateTime date)
		{
			DateTime previousDate;
			if (date.DayOfWeek == DayOfWeek.Monday)
			{
				previousDate = date.AddDays(-3);
			}
			else if (date.DayOfWeek == DayOfWeek.Sunday)
			{
				previousDate = date.AddDays(-2);
			}
			else
			{
				previousDate = date.AddDays(-1);
			}

			if (!CheckIsTradeDate(previousDate))
			{
				previousDate = GetPreviousTradeDate(previousDate);
			}

			return previousDate;
		}

		/// <summary>
		/// 当前时间是否是在净值出现变动时间内。
		/// 一般情况下，当天18：00到第二天9：00。
		/// </summary>
		/// <param name="date">输出：净值日期</param>
		/// <returns></returns>
		public static bool NowIsNetValueChangeTime(out DateTime date)
		{
			var hour = DateTime.Now.Hour;
			bool result = false;
			date = DateTime.MinValue;

			// 18:00-24:00
			if (hour > 18 && hour < 24)
			{
				date = DateTime.Today;
				result = true;
			}

			// 00:00-09:00
			if (hour >= 0 && hour <= 9)
			{
				date = DateTime.Today.AddDays(-1);
				result = true;
			}

			if (result)
			{// 附加交易日条件进行再次确认
				if (!TradeDateUtil.CheckIsTradeDate(date))
				{
					date = DateTime.MinValue;
					result = false;
				}
			}

			return result;
		}
	}
}
